/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = msmq_core.c                                                   */
/*  NOTE      = MSMQ协议解析                                                  */
/*  DATE      = 2015/08/13 by wuwk                                            */
/******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

#include "frservice_comm.h"
#include "frvar_field.h"
#include "msmq_core.h"
#include "msmq_analysis.h"
#include "msmq_comm.h"
#include "config.h"

extern void *g_p_apm_context;

#define MSMQ_REPORT_KEY_QUENAME     APM_REPORT_KEY_SESSION ".mq.queue"
#define MSMQ_REPORT_KEY_TOPIC     APM_REPORT_KEY_SESSION ".mq.topic"

FR_STATIC int __msmq_getdata_req_analysis(L7session_msmq_private *p_st_private
                                        , Conntrack *p_st_conn
                                        , Frhash_header *p_st_hash_report
                                        , Apm_packet *p_st_packet
                                        , char *p_data
                                        , unsigned int ui_data_len);

/*******************************************************************************
*  FUNC     :  释放Frvar_field 节点
*  ARGS     :  pp_st_data (Frvar_field 节点)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
//FR_STATIC void __msmq_frdata_free(Frvar_field **pp_st_data)
//{
//    if (pp_st_data == NULL || *pp_st_data == NULL)
//        return;
//
//    Frvar_field *p_st_data = *pp_st_data;
//    if (p_st_data->p_field_name)
//        frfree(p_st_data->p_field_name);
//
//    if (p_st_data->field_value.p_value)
//        frfree(p_st_data->field_value.p_value);
//
//    frfree(p_st_data);
//    *pp_st_data = NULL;
//
//    return;
//}

/*******************************************************************************
*  FUNC     :  Frlist_node 节点
*  ARGS     :  p_st_node (Frlist_node 节点)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
//FR_STATIC void __msmq_frdata_node_free(Frlist_node *p_st_node)
//{
//    if (p_st_node == NULL || p_st_node->data == NULL)
//        return;
//
//    Frvar_field *p_st_data = (Frvar_field *)p_st_node->data;
//    if (p_st_data->p_field_name)
//        frfree(p_st_data->p_field_name);
//
//    if (p_st_data->field_value.p_value)
//        frfree(p_st_data->field_value.p_value);
//
//    frfree(p_st_data);
//
//    return;
//}

/*******************************************************************************
*  FUNC     :  释放request数据
*  ARGS     :  p_st_req(请求数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void __msmq_reset_request(Msmq_frbyte_req *p_st_req)
{
    if (p_st_req == NULL)
        return;
    if (p_st_req->p_st_data_req)
        bytebuff_free(&p_st_req->p_st_data_req);
    frreport_body_free(&p_st_req->p_st_body_data_req);

    p_st_req->i_responserequired = 1;
    memset(&(p_st_req->st_trans_info.st_l4_trans), 0x00, sizeof(L4_transaction));

    return;
}

/*******************************************************************************
*  FUNC     :  复制frlist 节点
*  ARGS     :  p_lst_source (源节点)
            :  p_lst_dest(目标节点)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC void __msmq_frlist_copy(Frlist_header *p_lst_source, Frlist_header *p_lst_dest)
{
    Frlist_node *p_st_node_org=NULL, *p_st_node_clone=NULL;
    Frvar_field *p_st_field_org = NULL, *p_st_field_clone=NULL;

    p_st_node_org = FRLIST_FIRST_NODE(p_lst_source);

    while(p_st_node_org)
    {
        p_st_field_org =  (Frvar_field*)FRLIST_GET_NODE_DATA(p_st_node_org);
        p_st_field_clone = frvarfield_clone(p_st_field_org);
        if(p_st_field_clone)
        {
            p_st_node_clone = frlist_node_create(p_st_field_clone);
            if(p_st_node_clone == NULL)
                frvarfield_free(&p_st_field_clone);
            else
                frlist_push(p_lst_dest, p_st_node_clone);
        }

        p_st_node_org = FRLIST_NEXT_NODE(p_st_node_org);
    }

    return;
}

/*******************************************************************************
*  FUNC     :  复制L7 数据
*  ARGS     :  p_st_src (源数据)
            :  pp_st_dst(目标数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_body_l7data_copy(Frreport_body_data *p_st_src
                                    , Frreport_body_data **pp_st_dst)
{
    Frlist_header *p_lst = NULL;
    Frreport_body_data *p_st_dst = NULL;
    Frreport_l7data *p_st_l7data_src = NULL;

    if (p_st_src == NULL)
        return FR_FAIL;

    p_st_dst = (Frreport_body_data *)frmalloc(sizeof(Frreport_body_data));
    if (p_st_dst == NULL)
        goto err;

    memset(p_st_dst, 0x00, sizeof(Frreport_body_data));
    p_st_l7data_src = &(p_st_src->un_data.st_l7data);

    p_st_dst->em_type = p_st_src->em_type;
    p_st_dst->un_data.st_l7data.ip_proto = p_st_l7data_src->ip_proto;
    p_st_dst->un_data.st_l7data.src_ip = p_st_l7data_src->src_ip;
    p_st_dst->un_data.st_l7data.src_port = p_st_l7data_src->src_port;
    p_st_dst->un_data.st_l7data.dst_ip = p_st_l7data_src->dst_ip;
    p_st_dst->un_data.st_l7data.dst_port = p_st_l7data_src->dst_port;
    p_st_dst->un_data.st_l7data.i_l7_proto = p_st_l7data_src->i_l7_proto;

    /* 请求数据 */
    p_lst = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_src);
    if (p_lst == NULL)
        goto err;

     __msmq_frlist_copy(p_lst, &p_st_dst->un_data.st_l7data.st_hdr_req);

    frreport_body_l7list_free(&p_lst);

    /* session数据 */
    p_lst = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_src);
    if (p_lst == NULL)
        goto err;
    __msmq_frlist_copy(p_lst, &p_st_dst->un_data.st_l7data.st_hdr_comm);

    frreport_body_l7list_free(&p_lst);

    /* mq数据 */
    p_lst = FRREPORT_BODY_L7LIST_CLONE_MQ(p_st_src);
    if (p_lst == NULL)
        goto err;
    __msmq_frlist_copy(p_lst, &p_st_dst->un_data.st_l7data.st_hdr_mq);

    frreport_body_l7list_free(&p_lst);

    *pp_st_dst = p_st_dst;

    return FR_SUCC;

err:
    if (p_st_dst)
        frfree(p_st_dst);

    if (p_lst)
        frreport_body_l7list_free(&p_lst);

    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  复制请求数据
*  ARGS     :  p_st_src (源数据)
            :  pp_st_dst(目标数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_req_copy(Msmq_frbyte_req *p_st_src
                            , Msmq_frbyte_req **pp_st_dst)
{
    Msmq_frbyte_req *p_st_dst = NULL;
    Frreport_body_data *p_st_body_data = NULL;
    int i_ret = 0;

    if (p_st_src == NULL || p_st_src->p_st_body_data_req == NULL)
        return FR_FAIL;

    if (*pp_st_dst != NULL)
    {
        __msmq_reset_request(*pp_st_dst);
        frfree(*pp_st_dst);
    }

    p_st_dst = (Msmq_frbyte_req *)frmalloc(sizeof(Msmq_frbyte_req));
    if (p_st_dst == NULL)
        return FR_FAIL;
    memset(p_st_dst, 0x00, sizeof(Msmq_frbyte_req));

    /* 复制L7数据 */
    i_ret = __msmq_body_l7data_copy(p_st_src->p_st_body_data_req, &p_st_body_data);
    if (i_ret == FR_FAIL)
    {
        frfree(p_st_dst);
        return FR_FAIL;
    }

    p_st_dst->p_st_body_data_req = p_st_body_data;
    p_st_dst->ul_seq = p_st_src->ul_seq;
    p_st_dst->i_responserequired = p_st_src->i_responserequired;

    memcpy(&p_st_dst->st_trans_info, &p_st_src->st_trans_info, sizeof(Frtrans_info));

    *pp_st_dst = p_st_dst;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放report节点
*  ARGS     :  p_st_private(MSMQ私有数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void __msmq_report_list_free(L7session_msmq_private *p_st_private)
{
    Msmq_report_list *p_report_node = NULL;
    Msmq_report_list *p_report_node_next = NULL;

    if (p_st_private == NULL || p_st_private->p_lst_noreport_req == NULL)
        return;

    p_report_node = p_st_private->p_lst_noreport_req;
    while (p_report_node)
    {
        p_report_node_next = p_report_node->next;
        if (p_report_node->p_st_body_data)
            frreport_body_free(&p_report_node->p_st_body_data);
        frfree(p_report_node);
        p_report_node = p_report_node_next;
    }

    p_st_private->p_lst_noreport_req = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  取长度
*  ARGS     :  p_st_data (数据)
*           :  i_index(数据位置)
*           :  p_u16_len(取得的数值)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_get_msglen(Frbyte_Packet *p_st_data, int i_index, uint16_t *p_u16_len)
{
    char arr_tmp[3];
    uint16_t *p_u16 = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_u16_len == NULL)
        return FR_FAIL;

    memset(arr_tmp, 0x00, sizeof(arr_tmp));
    i_ret = bytebuff_get_bytes_at(p_st_data, i_index, 2, arr_tmp);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_u16 = (uint16_t *)arr_tmp;
    *p_u16_len = le16toh(*p_u16);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  初始化MSMQ session信息
*  ARGS     :  p_st_session (MSMQ session信息)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_init_private(L7_session *p_st_session)
{
    L7session_msmq_private *p_st_private_session = NULL;
    Msmq_frbyte_req *p_st_req = NULL;
    Msmq_frbyte_resp *p_st_resp = NULL;
    Msmq_L7session *p_st_l7_session = NULL;

    /* 申请整个私有session结构的内存 */
    p_st_private_session = (L7session_msmq_private *)frmalloc(sizeof(L7session_msmq_private));
    if (p_st_private_session == NULL)
        return FR_FAIL;

    memset(p_st_private_session, 0x00, sizeof(L7session_msmq_private));

    /* 申请请求数据结构内存 */
    p_st_req = (Msmq_frbyte_req *)frmalloc(sizeof(Msmq_frbyte_req));
    if (p_st_req == NULL)
    {
        frfree(p_st_private_session);
        return FR_FAIL;
    }
    memset(p_st_req, 0x00, sizeof(Msmq_frbyte_req));

    /* 申请响应数据结构内存 */
    p_st_resp = (Msmq_frbyte_resp *)frmalloc(sizeof(Msmq_frbyte_resp));
    if (p_st_resp == NULL)
    {
        frfree(p_st_private_session);
        frfree(p_st_req);
        return FR_FAIL;
    }
    memset(p_st_resp, 0x00, sizeof(Msmq_frbyte_resp));

    /* 申请session结构内存 */
    p_st_l7_session = (Msmq_L7session *)frmalloc(sizeof(Msmq_L7session));
    if (p_st_l7_session == NULL)
    {
        frfree(p_st_private_session);
        frfree(p_st_req);
        frfree(p_st_resp);
        return FR_FAIL;
    }
    memset(p_st_l7_session, 0x00, sizeof(Msmq_L7session));

    p_st_req->i_responserequired = 1;
    p_st_private_session->p_st_req = p_st_req;
    p_st_private_session->p_st_resp = p_st_resp;
    p_st_private_session->p_st_l7_session = p_st_l7_session;

    p_st_session->p_session_private = p_st_private_session;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放解析完的数据
*  ARGS     :  p_st_private(MSMQ私有数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __msmq_reset_private(L7session_msmq_private *p_st_private)
{
    Msmq_frbyte_req *p_st_req = NULL;
    Msmq_frbyte_resp *p_st_resp = NULL;

    if (p_st_private == NULL)
        return;

    memset(&(p_st_private->st_trans_info.st_l4_trans), 0x00, sizeof(L4_transaction));

    p_st_req = p_st_private->p_st_req;
    if (p_st_req)
    {
        if (p_st_req->p_st_data_req)
            bytebuff_free(&p_st_req->p_st_data_req);

        frreport_body_free(&p_st_req->p_st_body_data_req);
    }

    p_st_resp = p_st_private->p_st_resp;
    if (p_st_resp)
    {
        if (p_st_resp->p_st_data_resp)
            bytebuff_free(&p_st_resp->p_st_data_resp);

        frreport_body_free(&p_st_resp->p_st_body_data_resp);
    }

    return;
}

/*******************************************************************************
*  FUNC     :  释放request和response数据
*  ARGS     :  p_st_private(MSMQ私有数据)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
FR_STATIC void __msmq_reset_round(L7session_msmq_private *p_st_private)
{
    Msmq_frbyte_resp *p_st_resp = NULL;

    if (p_st_private == NULL)
        return;

    /* 初始化响应节点 */
    p_st_resp = p_st_private->p_st_resp;
    if (p_st_resp)
    {
        if (p_st_resp->p_st_data_resp)
            bytebuff_free(&p_st_resp->p_st_data_resp);
        frreport_body_free(&p_st_resp->p_st_body_data_resp);
    }

    __msmq_reset_request(p_st_private->p_st_last_req);
    frfree(p_st_private->p_st_last_req);
    p_st_private->p_st_last_req = NULL;
    /* 释放请求链表 */
    __msmq_report_list_free(p_st_private);

    p_st_private->i_msg_type = MSMQ_MSG_TYPE_PTP;
//    p_st_private->i_resp_report = MSMQ_NO;
    p_st_private->i_need_resp  = MSMQ_NO;
    memset(&(p_st_private->st_trans_info.st_l4_trans), 0x00, sizeof(L4_transaction));

    return;
}

/*******************************************************************************
*  FUNC     :  请求数据复制到链表用做上报
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_lst_req(上报链表)
            :  i_responserequired(是否需要应答)
            :  ul_seq(序号)
            :  p_st_l4_trans(传输信息)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_add_report_list(L7session_msmq_private *p_st_private
                                   , Frreport_body_data *p_lst_req
                                   , int i_responserequired
                                   , unsigned long ul_seq
                                   , L4_transaction *p_st_l4_trans)
{
    Msmq_report_list *p_node = NULL;
    Msmq_report_list *p_node_next = NULL;

    if (p_st_private == NULL || p_lst_req == NULL || p_st_l4_trans == NULL)
        return FR_FAIL;

    p_node = (Msmq_report_list *)frmalloc(sizeof(Msmq_report_list));
    if (p_node == NULL)
        return FR_FAIL;

    memset(p_node, 0x00, sizeof(Msmq_report_list));

    p_node->i_responserequired = i_responserequired;
    p_node->ul_seq = ul_seq;
    p_node->p_st_body_data = p_lst_req;
    memcpy(&(p_node->st_trans_info.st_l4_trans), p_st_l4_trans, sizeof(L4_transaction));

    /* 第一个 */
    if (p_st_private->p_lst_noreport_req == NULL)
    {
        p_st_private->p_lst_noreport_req = p_node;
        return FR_SUCC;
    }

    p_node_next = p_st_private->p_lst_noreport_req;
    while (p_node_next->next)
    {
        p_node_next = p_node_next->next;
    }

    p_node_next->next = p_node;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  MSMQ session数据添加
*  ARGS     :  p_st_body_data(IBM MQ上报数据)
            :  p_st_l7_session(session数据)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_add_session(Frreport_body_data *p_st_body_data
                               , Msmq_L7session *p_st_l7_session
                               , int i_msg_type)
{
    int i_ret = 0;

    if (p_st_body_data == NULL || p_st_l7_session == NULL)
        return FR_FAIL;

    /* 服务名 */
    if (p_st_l7_session->p_server != NULL)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_SERVER, p_st_l7_session->p_server);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* 队列名 */
    if (p_st_l7_session->p_queue_name != NULL)
    {
        if (i_msg_type == MSMQ_MSG_TYPE_PTP)
            i_ret = frreport_body_l7_add_str(p_st_body_data, MSMQ_REPORT_KEY_QUENAME, p_st_l7_session->p_queue_name);
        else
            i_ret = frreport_body_l7_add_str(p_st_body_data, MSMQ_REPORT_KEY_TOPIC, p_st_l7_session->p_queue_name);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    /* title */
    if (p_st_l7_session->p_title != NULL)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_st_l7_session->p_title);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  MSMQ请求数据上报
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_l4_trans(传输信息)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_req_report(L7session_msmq_private *p_st_private
                              , Frhash_header *p_st_hash_report
                              , L4_transaction *p_st_l4_trans)
{
    Msmq_report_list *p_report_lst = NULL;
    Frreport_data *p_st_report_data = NULL;
    Frreport_body_data *p_report_data = NULL;
    Msmq_frbyte_resp *p_st_resp = NULL;
    Frreport_body_data *p_body_data_report = NULL;
    Msmq_L7session *p_st_l7_session = NULL;
    int i_ret = 0;

    p_report_lst = p_st_private->p_lst_noreport_req;
    p_st_resp = p_st_private->p_st_resp;

    while (p_report_lst)
    {
        if (p_report_lst->i_reported == 1)
        {
            p_report_lst = p_report_lst->next;
            continue;
        }

        p_report_data = p_report_lst->p_st_body_data;
        /* 最后一个请求isResponseRequired设为1 */
        if (p_report_lst->next == NULL)
        {
            /* 修改请求的i_responserequired值 */
            if (frreport_body_l7_del_index(p_report_data, "request.isResponseRequired", 0)== FR_FAIL)
                goto err;
            if (frreport_body_l7_add_int(p_report_data, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
                goto err;
        }

        if (__msmq_body_l7data_copy(p_report_data, &p_body_data_report) == FR_FAIL)
            goto err;

        p_st_l7_session = p_st_private->p_st_l7_session;
        /* GET和NOTIFY的请求要加上session信息 */
        if (p_st_private->i_is_get == 1 && p_st_l7_session != NULL)
        {
            if (p_st_l7_session->p_queue_name)
            {
                if (p_st_private->i_msg_type == MSMQ_MSG_TYPE_PTP)
                    i_ret = frreport_body_l7_add_str(p_body_data_report, MSMQ_REPORT_KEY_QUENAME, p_st_l7_session->p_queue_name);
                else
                    i_ret = frreport_body_l7_add_str(p_body_data_report, MSMQ_REPORT_KEY_TOPIC, p_st_l7_session->p_queue_name);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
            }

            if (p_st_l7_session->p_title)
            {
                i_ret = frreport_body_l7_add_str(p_body_data_report, APM_REPORT_KEY_TRANS_TITLE, p_st_l7_session->p_title);
                if (i_ret == FR_FAIL)
                    return FR_FAIL;
            }
        }

        /* 数据上报 */
        if (p_st_private->i_msg_type == MSMQ_MSG_TYPE_PUB)
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_PUB);
        else
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);

        if (p_st_report_data == NULL)
            goto err;

        if (frreport_data_add_body(p_st_report_data, p_body_data_report) == FR_FAIL)
            goto err;
        p_body_data_report = NULL;

        if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
            goto err;
        p_st_report_data = NULL;

        p_st_l4_trans->st_request_time.tv_sec = p_report_lst->st_trans_info.st_l4_trans.st_request_time.tv_sec;
        p_st_l4_trans->st_request_time.tv_usec = p_report_lst->st_trans_info.st_l4_trans.st_request_time.tv_usec;

        p_report_lst->i_reported = 1;

        p_report_lst = p_report_lst->next;
    }

    return FR_SUCC;

err:
    if (p_st_report_data)
        frreport_data_hash(p_st_hash_report, p_st_report_data);

    if (p_body_data_report)
        frreport_body_free(&p_body_data_report);

    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  MSMQ数据上报
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(数据)
            :  i_req_resp(请求/响应标记)
            :  i_report_flag(是否直接上报 0:上报 1:存到链表)
*  RTN      :  FR_FAIL                   失败
*           :  FR_SUCC                   成功
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_data_report(L7session_msmq_private *p_st_private
                               , Conntrack *p_st_conn
                               , Frhash_header *p_st_hash_report
                               , Apm_packet *p_st_packet
                               , int i_req_resp
                               , int i_report_flag)
{
    L4_transaction *p_st_l4_trans = NULL;
    L4_transaction st_l4_trans_req;
    Frtrans_info  st_trans_info;
    Msmq_frbyte_req *p_st_req = NULL;
    Msmq_frbyte_resp *p_st_resp = NULL;
    Frreport_body_data *p_st_body_data_req = NULL;
    Frlist_header *p_lst_header_req = NULL;
    Frlist_header *p_lst_header_mq = NULL;
    Frreport_data *p_st_report_data = NULL;
    Msmq_frbyte_req *p_st_last_req = NULL;
    int i_ret = 0;

    if (p_st_private == NULL)
        return FR_FAIL;

    /* st_trans_info数据初始化 */
    memset(&st_trans_info, 0x00, sizeof(Frtrans_info));
    memset(&st_l4_trans_req, 0x00, sizeof(L4_transaction));

    /* 设置p_st_l4_trans */
    p_st_l4_trans = &(st_trans_info.st_l4_trans);

    /* request数据保存 */
    if (i_req_resp == MSMQ_REQUEST)
    {
        p_st_req = p_st_private->p_st_req;

        if (frreport_body_l7_add_int(p_st_req->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, p_st_req->i_responserequired) == FR_FAIL)
            goto err;

        i_ret = __msmq_body_l7data_copy(p_st_req->p_st_body_data_req
                                      , &p_st_body_data_req);
        if (i_ret == FR_FAIL)
            goto err;

        /* 添加session信息 */
        i_ret = __msmq_add_session(p_st_body_data_req, p_st_private->p_st_l7_session, p_st_private->i_msg_type);
        if (i_ret == FR_FAIL)
            goto err;

        i_ret = __msmq_add_report_list(p_st_private, p_st_body_data_req
                                         , p_st_req->i_responserequired
                                         , p_st_req->ul_seq
                                         , &(p_st_req->st_trans_info.st_l4_trans));
        if (i_ret == FR_FAIL)
            goto err;
        p_st_body_data_req = NULL;
    }
    else  /* response数据上报 */
    {
        /* request数据上报 */
        i_ret = __msmq_req_report(p_st_private, p_st_hash_report, &st_l4_trans_req);
        if (i_ret == FR_FAIL)
            goto err;

        p_st_resp = p_st_private->p_st_resp;

        memcpy(p_st_l4_trans, &(p_st_private->st_trans_info.st_l4_trans), sizeof(L4_transaction));
        /* 响应开始时间 */
        if (frreport_body_l7_add_timeval(p_st_resp->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
            goto err;

        /* 响应结束时间 */
        if (frreport_body_l7_add_timeval(p_st_resp->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
            goto err;

        i_ret = frreport_body_l7_add_connInfo(p_st_resp->p_st_body_data_resp, p_st_conn);
        if (i_ret == FR_FAIL)
            goto err;

        /* 添加session信息 */
        i_ret = __msmq_add_session(p_st_resp->p_st_body_data_resp, p_st_private->p_st_l7_session, p_st_private->i_msg_type);
        if (i_ret == FR_FAIL)
            goto err;

        p_st_last_req = p_st_private->p_st_last_req;
        if (p_st_last_req != NULL)
        {
            if (p_st_last_req->p_st_body_data_req)
            {
                /* 修改请求的i_responserequired值 */
                if (frreport_body_l7_del_index(p_st_last_req->p_st_body_data_req, "request.isResponseRequired", 0)== FR_FAIL)
                    goto err;
                if (frreport_body_l7_add_int(p_st_last_req->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
                    goto err;

                /* 请求数据追加 */
                p_lst_header_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_last_req->p_st_body_data_req);
                if (FRREPORT_BODY_L7LIST_SET_REQ(p_st_resp->p_st_body_data_resp, &p_lst_header_req) == FR_FAIL)
                    goto err;
                p_st_l4_trans->st_request_time = p_st_last_req->st_trans_info.st_l4_trans.st_request_time;

                p_lst_header_mq = FRREPORT_BODY_L7LIST_CLONE_MQ(p_st_last_req->p_st_body_data_req);
                if (FRREPORT_BODY_L7LIST_SET_MQ(p_st_resp->p_st_body_data_resp, &p_lst_header_mq) == FR_FAIL)
                    goto err;
            }
        }

        if (p_st_l4_trans->st_request_time.tv_sec != 0)
        {
            /* 服务器运行时间 */
            p_st_l4_trans->ul_response_time_firstbyte_us = frtime_diff(&(p_st_l4_trans->st_request_time), &(p_st_private->st_trans_info.st_l4_trans.st_response_time_first_byte));
            if (frreport_body_l7_add_ulong(p_st_resp->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, p_st_l4_trans->ul_response_time_firstbyte_us) == FR_FAIL)
                goto err;
        }

        /* 下载时间 */
        p_st_l4_trans->ul_response_time_us = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_private->st_trans_info.st_l4_trans.st_response_time));
        if (frreport_body_l7_add_ulong(p_st_resp->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, p_st_l4_trans->ul_response_time_us) == FR_FAIL)
            goto err;

        /* 响应的字节数 */
        if (frreport_body_l7_add_long(p_st_resp->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
            goto err;

        /* 数据上报 */
        if (p_st_private->i_msg_type == MSMQ_MSG_TYPE_NOTIFY)
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_NOTIFY);
        else
            p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);

        if (p_st_report_data == NULL)
            goto err;

        if (frreport_data_add_body(p_st_report_data, p_st_resp->p_st_body_data_resp) == FR_FAIL)
            goto err;
        p_st_resp->p_st_body_data_resp = NULL;

        if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
            goto err;
        p_st_report_data = NULL;

        if (i_ret == FR_FAIL)
            goto err;
    }
    return FR_SUCC;

err:
    if (p_st_body_data_req)
        frreport_body_free(&p_st_body_data_req);

    if (p_lst_header_req)
        frreport_body_l7list_free(&p_lst_header_req);

    if (p_lst_header_mq)
        frreport_body_l7list_free(&p_lst_header_mq);

    if (p_st_report_data)
        frreport_data_hash(p_st_hash_report, p_st_report_data);

    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  MSMQ的请求解析
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
            :  i_report_flag(是否直接上报 0:上报 1:存到链表)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_req_analysis(L7session_msmq_private *p_st_private
                                , Conntrack *p_st_conn
                                , Frhash_header *p_st_hash_report
                                , Apm_packet *p_st_packet
                                , int i_report_flag)
{
    int i_ret = 0;
    int i_need_report = MSMQ_NO;
    unsigned long ul_time_diff = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Msmq_frbyte_req *p_st_req = NULL;

    if (p_st_private == NULL || p_st_private->p_st_req == NULL
        || p_st_conn == NULL || p_st_hash_report == NULL || p_st_packet == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_req = p_st_private->p_st_req;
    p_st_l4_trans = &(p_st_req->st_trans_info.st_l4_trans);

    if (p_st_l4_trans->st_request_time_first_byte.tv_sec == 0
        && p_st_l4_trans->st_request_time_first_byte.tv_usec == 0)
    {
        /* 请求发起的第一个数据包时间 */
        p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        p_st_req->ul_seq = frct_seq_increase(p_st_conn);

        p_st_req->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_req->p_st_body_data_req == NULL)
            return APM_L7_ANALYZE_FAIL;

        if (frreport_body_l7_add_connInfo(p_st_req->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto err;

        if (frreport_body_l7_add_ulong(p_st_req->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_req->ul_seq) == FR_FAIL)
            goto err;

        if (frreport_body_l7_add_timeval(p_st_req->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_packet->st_timestamp) == FR_FAIL)
            goto err;
    }

    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
    if (frreport_body_l7_add_timeval(p_st_req->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_packet->st_timestamp) == FR_FAIL)
        goto err;

    /* 发送时间 */
    ul_time_diff = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    if (frreport_body_l7_add_ulong(p_st_req->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_time_diff) == FR_FAIL)
        goto err;

    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes += p_st_req->ui_data_len;
    if (frreport_body_l7_add_long(p_st_req->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto err;

    /* MSMQ数据解析 */
    i_ret = msmq_analysis_data(p_st_private, p_st_req->p_st_body_data_req, MSMQ_REQUEST, &i_need_report);
    if (i_ret == FR_SUCC)
    {
        if (i_need_report == MSMQ_YES)
        {
            /* 数据上报 */
            i_ret = __msmq_data_report(p_st_private, p_st_conn, p_st_hash_report
                                 , p_st_packet, MSMQ_REQUEST, i_report_flag);
            if (i_ret == APM_L7_ANALYZE_TODO)
                return i_ret;
            else if (i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;

            i_ret = __msmq_req_copy(p_st_req, &p_st_private->p_st_last_req);
            if (i_ret == FR_FAIL)
                return APM_L7_ANALYZE_FAIL;
        }

        __msmq_reset_request(p_st_req);
//        p_st_private->i_msg_type = MSMQ_MSG_TYPE_PTP;

        return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
    }

    return i_ret;

err:
    if (p_st_req->p_st_body_data_req)
        frreport_body_free(&p_st_req->p_st_body_data_req);

    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  MSMQ的响应解析
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_resp_analysis(L7session_msmq_private *p_st_private
                                 , Conntrack *p_st_conn
                                 , Frhash_header *p_st_hash_report
                                 , Apm_packet *p_st_packet)
{
    int i_ret = 0;
    int i_need_report = MSMQ_NO;
    L4_transaction *p_st_l4_trans = NULL;
    Msmq_frbyte_resp *p_st_resp = NULL;

    if (p_st_private == NULL || p_st_private->p_st_resp == NULL
        || p_st_conn == NULL || p_st_hash_report == NULL || p_st_packet == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_resp = p_st_private->p_st_resp;
    p_st_l4_trans = &(p_st_private->st_trans_info.st_l4_trans);

    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0
        && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
    {
        /* 响应发起的第一个数据包时间 */
        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        p_st_resp->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_resp->p_st_data_resp == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    /* 结束时间 */
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    /* 响应的字节数 */
    p_st_l4_trans->l_response_bytes = p_st_resp->ui_data_len;

    /* MSMQ体部数据解析 */
    i_ret = msmq_analysis_data(p_st_private, p_st_resp->p_st_body_data_resp, MSMQ_RESPONSE, &i_need_report);
    if (i_ret == FR_SUCC)
    {
        //if (p_st_private->i_resp_report == MSMQ_YES)
        if (i_need_report == MSMQ_YES)
        {
            /* 数据上报 */
            i_ret = __msmq_data_report(p_st_private, p_st_conn, p_st_hash_report
                                      , p_st_packet, MSMQ_RESPONSE, 0);
            if (i_ret == FR_FAIL)
                goto err;
        }
        else if (p_st_private->i_protocol_type == MSMQ_DECRPC)
            __msmq_report_list_free(p_st_private);

        __msmq_reset_round(p_st_private);
        p_st_private->i_msg_type = MSMQ_MSG_TYPE_PTP;

        return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }

    return i_ret;

err:
    if (p_st_resp->p_st_body_data_resp)
        frreport_body_free(&p_st_resp->p_st_body_data_resp);

    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  取得完整的请求数据包并解析
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
            :  p_data(入力数据)
            :  ui_data_len(数据长度)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_getdata_req_analysis(L7session_msmq_private *p_st_private
                                        , Conntrack *p_st_conn
                                        , Frhash_header *p_st_hash_report
                                        , Apm_packet *p_st_packet
                                        , char *p_data
                                        , unsigned int ui_data_len)
{
    Msmq_frbyte_req *p_st_req = NULL;
    char arr_len[3];
    uint16_t *p_u16_len = NULL;
    uint16_t u16_len = 0;
    int i_report_flag = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_conn == NULL || p_st_hash_report == NULL
        || p_st_packet == NULL || p_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    if (ui_data_len == 0)
        return APM_L7_ANALYZE_TODO;

    p_st_req = p_st_private->p_st_req;
    if (p_st_req->p_st_data_req == NULL)
    {
        /* 做成请求bytebuffer */
        p_st_req->p_st_data_req = bytebuff_creat();
        if (p_st_req->p_st_data_req == NULL)
            goto err;
    }

    /* 上次的数据包不完整 */
    if (p_st_req->ui_recv_len)
    {
        /* 前次数据长度小于10, 没有取到数据长度 */
        if (p_st_req->ui_data_len == 0)
        {
            /* 前次数据+本次数据的长度小于10 */
            if (p_st_req->ui_recv_len + ui_data_len < 10)
            {
                p_st_req->ui_recv_len += ui_data_len;
                i_ret = bytebuff_add(p_st_req->p_st_data_req, p_data, ui_data_len);
                if (i_ret != FR_SUCC)
                    goto err;
                return APM_L7_ANALYZE_TODO;
            }
            else
            {
                i_ret = __msmq_get_msglen(p_st_req->p_st_data_req, 8, &u16_len);
                if (i_ret != FR_SUCC)
                    goto err;
                p_st_req->ui_data_len = u16_len;
            }
        }
        /* 还需要接收的数据长度大于本次数据的长度，即本次数据不够完成本次解析 */
        if (p_st_req->ui_left_len > ui_data_len)
        {
            /* 将本次数据存入buffer */
            i_ret = bytebuff_add(p_st_req->p_st_data_req, p_data, ui_data_len);
            if (i_ret != FR_SUCC)
                goto err;
            p_st_req->ui_left_len -= ui_data_len;
            return APM_L7_ANALYZE_TODO;
        }

        /* 获取本次解析还需要的数据 */
        i_ret = bytebuff_add(p_st_req->p_st_data_req, p_data, p_st_req->ui_left_len);
        if (i_ret != FR_SUCC)
            goto err;

        p_data += p_st_req->ui_left_len;
        ui_data_len -= p_st_req->ui_left_len;
        p_st_req->ui_left_len = 0;
        p_st_req->ui_recv_len = 0;

        if (ui_data_len > 0 && *p_data != '\0')
            i_report_flag = 1;
        /* 解析当前数据 */
        i_ret = __msmq_req_analysis(p_st_private, p_st_conn, p_st_hash_report, p_st_packet, i_report_flag);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto err;
        else
        {
            bytebuff_free(&p_st_req->p_st_data_req);
            /* 还需要接收数据长度的初始化 */
            p_st_req->ui_left_len = 0;
            p_st_req->ui_recv_len = 0;
        }

        if (ui_data_len > 0)
        {
            i_ret = __msmq_getdata_req_analysis(p_st_private, p_st_conn, p_st_hash_report
                                              , p_st_packet, p_data, ui_data_len);
            if (i_ret == APM_L7_ANALYZE_FAIL)
                goto err;
        }
        return i_ret;
    }

    if (*p_data == '\0')
    {
        bytebuff_free(&p_st_req->p_st_data_req);
        /* 还需要接收数据长度的初始化 */
        p_st_req->ui_left_len = 0;
        p_st_req->ui_recv_len = 0;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 上次的数据包完整，开始新的数据包解析 */
    if (ui_data_len > 10)
    {
        memset(arr_len, 0x00, sizeof(arr_len));
        memcpy(arr_len, p_data + 8, 2);
        p_u16_len = (uint16_t *)arr_len;
        p_st_req->ui_data_len = *p_u16_len;
    }
    else
    {
        i_ret = bytebuff_add(p_st_req->p_st_data_req, p_data, ui_data_len);
        if (i_ret != FR_SUCC)
            goto err;
        p_st_req->ui_recv_len = ui_data_len;
        return APM_L7_ANALYZE_TODO;
    }

    /* 数据长度不够 */
    if (p_st_req->ui_data_len > ui_data_len)
    {
        i_ret = bytebuff_add(p_st_req->p_st_data_req, p_data, ui_data_len);
        if (i_ret != FR_SUCC)
            goto err;
        p_st_req->ui_left_len = p_st_req->ui_data_len - ui_data_len;
        p_st_req->ui_recv_len = ui_data_len;
        return APM_L7_ANALYZE_TODO;
    }

    i_ret = bytebuff_add(p_st_req->p_st_data_req, p_data, p_st_req->ui_data_len);
    if (i_ret != FR_SUCC)
        goto err;

    p_data += p_st_req->ui_data_len;
    ui_data_len -= p_st_req->ui_data_len;
    if (ui_data_len > 0 && *p_data != '\0')
        i_report_flag = 1;

    /* 解析数据 */
    i_ret = __msmq_req_analysis(p_st_private, p_st_conn, p_st_hash_report, p_st_packet, i_report_flag);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto err;
    else
    {
        if (p_st_req->p_st_data_req)
            bytebuff_free(&p_st_req->p_st_data_req);
        /* 还需要接收数据长度的初始化 */
        p_st_req->ui_left_len = 0;
        p_st_req->ui_recv_len = 0;
    }

    if (ui_data_len > 0)
    {
        i_ret = __msmq_getdata_req_analysis(p_st_private, p_st_conn, p_st_hash_report
                                          , p_st_packet, p_data, ui_data_len);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto err;
    }
    return i_ret;

err:
    __msmq_reset_private(p_st_private);
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  取得完整的响应数据包并解析
*  ARGS     :  p_st_private(MSMQ私有数据)
            :  p_st_conn(入力链接信息)
            :  p_st_hash_report(保存Frreport_data)
            :  p_st_packet(入力packet信息)
            :  p_data(入力数据)
            :  ui_data_len(数据长度)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
FR_STATIC int __msmq_getdata_resp_analysis(L7session_msmq_private *p_st_private
                                         , Conntrack *p_st_conn
                                         , Frhash_header *p_st_hash_report
                                         , Apm_packet *p_st_packet
                                         , char *p_data
                                         , unsigned int ui_data_len)
{
    Msmq_frbyte_resp *p_st_resp = NULL;
    char arr_len[3];
    uint16_t *p_u16_len = NULL;
    uint16_t u16_len = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_conn == NULL || p_st_hash_report == NULL
        || p_st_packet == NULL || p_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    if (ui_data_len == 0)
        return APM_L7_ANALYZE_TODO;

    p_st_resp = p_st_private->p_st_resp;
    if (p_st_resp->p_st_data_resp == NULL)
    {
        /* 做成请求bytebuffer */
        p_st_resp->p_st_data_resp = bytebuff_creat();
        if (p_st_resp->p_st_data_resp == NULL)
            goto err;
    }

    /* 上次的数据包不完整 */
    if (p_st_resp->ui_recv_len)
    {
        /* 前次数据长度小于10, 没有取到数据长度 */
        if (p_st_resp->ui_data_len == 0)
        {
            /* 前次数据+本次数据的长度小于10 */
            if (p_st_resp->ui_recv_len + ui_data_len < 10)
            {
                p_st_resp->ui_recv_len += ui_data_len;
                i_ret = bytebuff_add(p_st_resp->p_st_data_resp, p_data, ui_data_len);
                if (i_ret != FR_SUCC)
                    goto err;
                return APM_L7_ANALYZE_TODO;
            }
            else
            {
                i_ret = __msmq_get_msglen(p_st_resp->p_st_data_resp, 8, &u16_len);
                if (i_ret != FR_SUCC)
                    goto err;
                p_st_resp->ui_data_len = u16_len;
            }
        }
        /* 还需要接收的数据长度大于本次数据的长度，即本次数据不够完成本次解析 */
        if (p_st_resp->ui_left_len > ui_data_len)
        {
            /* 将本次数据存入buffer */
            i_ret = bytebuff_add(p_st_resp->p_st_data_resp, p_data, ui_data_len);
            if (i_ret != FR_SUCC)
                goto err;
            p_st_resp->ui_left_len -= ui_data_len;
            return APM_L7_ANALYZE_TODO;
        }

        /* 获取本次解析还需要的数据 */
        i_ret = bytebuff_add(p_st_resp->p_st_data_resp, p_data, p_st_resp->ui_left_len);
        if (i_ret != FR_SUCC)
            goto err;

        /* 解析当前数据 */
        i_ret = __msmq_resp_analysis(p_st_private, p_st_conn, p_st_hash_report, p_st_packet);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto err;
        else
        {
            bytebuff_free(&p_st_resp->p_st_data_resp);
            /* 还需要接收数据长度的初始化 */
            p_st_resp->ui_left_len = 0;
            p_st_resp->ui_recv_len = 0;
            return APM_L7_ANALYZE_SUCC;
        }
    }

    if (*p_data == '\0')
    {
        bytebuff_free(&p_st_resp->p_st_data_resp);
        /* 还需要接收数据长度的初始化 */
        p_st_resp->ui_left_len = 0;
        p_st_resp->ui_recv_len = 0;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 上次的数据包完整，开始新的数据包解析 */
    if (ui_data_len != 0)
    {
        i_ret = bytebuff_add(p_st_resp->p_st_data_resp, p_data, ui_data_len);
        if (i_ret != FR_SUCC)
            goto err;
    }

    if (ui_data_len > 10)
    {
        memset(arr_len, 0x00, sizeof(arr_len));
        memcpy(arr_len, p_data + 8, 2);
        p_u16_len = (uint16_t *)arr_len;
        p_st_resp->ui_data_len = *p_u16_len;
//        p_st_resp->ui_data_len = ntohs(*p_u16_len);
    }
    else
    {
        p_st_resp->ui_recv_len = ui_data_len;
        return APM_L7_ANALYZE_TODO;
    }

    /* 数据长度不够 */
    if (p_st_resp->ui_data_len > ui_data_len)
    {
        p_st_resp->ui_left_len = p_st_resp->ui_data_len - ui_data_len;
        p_st_resp->ui_recv_len = ui_data_len;
        return APM_L7_ANALYZE_TODO;
    }

    /* 解析数据 */
    i_ret = __msmq_resp_analysis(p_st_private, p_st_conn, p_st_hash_report, p_st_packet);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto err;
    else
    {
        if (p_st_resp->p_st_data_resp)
            bytebuff_free(&p_st_resp->p_st_data_resp);
        /* 还需要接收数据长度的初始化 */
        p_st_resp->ui_left_len = 0;
        p_st_resp->ui_recv_len = 0;
        return APM_L7_ANALYZE_SUCC;
    }

err:
    __msmq_reset_private(p_st_private);
    return APM_L7_ANALYZE_FAIL;
}

/*******************************************************************************
*  FUNC     :  私有信息销毁
*  ARGS     :  p_private_session(MSMQ的私有session数据)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
int msmq_session_destroy(void *p_private_session)
{
    L7session_msmq_private *p_st_private = NULL;
    Msmq_frbyte_resp *p_st_resp = NULL;
    Msmq_L7session *p_st_l7_session = NULL;

    /* 判断session是否为空 */
    if (p_private_session == NULL)
        return FR_SUCC;

    p_st_private = (L7session_msmq_private *)p_private_session;

    p_st_resp = p_st_private->p_st_resp;
    p_st_l7_session = p_st_private->p_st_l7_session;

    __msmq_reset_request(p_st_private->p_st_req);
    __msmq_reset_request(p_st_private->p_st_last_req);

    if (p_st_resp)
    {
        if (p_st_resp->p_st_data_resp)
            bytebuff_free(&p_st_resp->p_st_data_resp);
        frreport_body_free(&p_st_resp->p_st_body_data_resp);
    }

    if (p_st_l7_session)
    {
        if (p_st_l7_session->p_server)
            frfree(p_st_l7_session->p_server);
        if (p_st_l7_session->p_queue_name)
            frfree(p_st_l7_session->p_queue_name);
        if (p_st_l7_session->p_title)
            frfree(p_st_l7_session->p_title);

        frfree(p_st_l7_session);
    }

    __msmq_report_list_free(p_st_private);

    frfree(p_st_private->p_st_req);
    frfree(p_st_private->p_st_last_req);
    frfree(p_st_resp);
    frfree(p_st_private);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  判断当前数据链路是否是msmq协议
*  ARGS     :  p_st_conn(入力链接信息)
*           :  p_st_packet(入力数据包)
*  RTN      :  APM_L7_IS_NO   (NO)
*              APM_L7_IS_YES  (YES)
*  NOTE     :
*******************************************************************************/
int msmq_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    char *p_payload = NULL;
    unsigned char *p_payload_tmp = NULL;
    unsigned char *p_lior_index = NULL;
    unsigned int ui_len = 0;
    uint32_t u32_priority = 0;
    uint16_t u16_len = 0;
    uint16_t *p_s_tmp = NULL;
    char arr_len[3];
    int i_ret = 0;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_packet->p_payload == NULL)
        return APM_L7_IS_NO;

    p_payload = p_st_packet->p_payload;
    p_payload_tmp = (unsigned char *)p_payload;
    ui_len = p_st_packet->ui_payload_len;

    if ((*p_payload_tmp != '\x10' && *p_payload_tmp != '\x05') || ui_len < 10)
        goto end;
 //       return APM_L7_IS_NO;

    /* DECRPC */
    if (*p_payload_tmp == '\x05')
    {
        if (*(p_payload_tmp + 1) != 0 && *(p_payload_tmp + 1) != 1)
            goto end;
//            return APM_L7_IS_NO;

        if (*(p_payload_tmp + 2) > 20)
            goto end;
//            return APM_L7_IS_NO;
    }

    p_lior_index = (unsigned char *)frmemstr((char *)p_payload_tmp, ui_len, (char *)MSMQ_STR_LIOR, 4);
    if (p_lior_index - p_payload_tmp < 4)
        goto end;
//        return APM_L7_IS_NO;
    else
        p_payload_tmp = p_lior_index - 4;

    /* 方向明确 */
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_KNOWN)
    {
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        return APM_L7_IS_YES;
    }

    if (ui_len <= MSMQ_HEAD_LEN + 30)
        goto end;
//        return APM_L7_IS_NO;

    u32_priority = *(p_payload_tmp + 2);
    p_payload_tmp += MSMQ_HEAD_LEN + 28;
    memset(arr_len, 0x00, sizeof(arr_len));
    memcpy(arr_len, p_payload_tmp, 2);
    p_s_tmp = (uint16_t *)arr_len;
    u16_len = le16toh(*p_s_tmp);

    /* 没有direct信息并且消息优先级不对 */
    if (((u16_len == 0 || *(p_payload_tmp + 2) == '\0') && msmq_check_msg_priority(u32_priority) == MSMQ_FALSE)
        || *(p_st_packet->p_payload) == '\x05')
    {
        i_ret = frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
        if (i_ret != FR_SUCC)
        {
            frdbg("frcap_set_cs_srv failed\n");
            return APM_L7_IS_NO;
        }
    }

    frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
    p_st_conn->flg_direct_known = FR_DIRECT_KNOWN;
    return APM_L7_IS_YES;

end:
    /* 长度为0的数据不进行识别协议查询 */
    if (ui_len == 0)
        return APM_L7_IS_NO;

    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*******************************************************************************
*  FUNC     :  MSMQ的packet解析
*  ARGS     :  p_st_conn(入力链接信息)
            :  p_st_packet(入力packet信息)
            :  p_st_hash_report(保存Frreport_data)
*  RTN      :  参照module.h
*  NOTE     :
*******************************************************************************/
int msmq_analysis(Conntrack *p_st_conn
                , Apm_packet *p_st_packet
                , Frhash_header *p_st_hash_report)
{
    L7session_msmq_private *p_st_private = NULL;
    L7_session *p_st_session = NULL;
    int i_ret = 0;

    if (p_st_conn == NULL || p_st_packet == NULL
         || p_st_hash_report == NULL)
         return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    /*
    * 如果入力p_st_packet是FIN包, 说明本次MSMQ的connection结束,
    * 释放本次session信息. 如果入力p_st_packet是SYN包,说明新的MSMQ的
    * connection开始了, 释放上次可能残留的session信息
    */
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN
        || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        /* 销毁所有相关本次MSMQ的connection的数据 */
        msmq_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

     /* 本次链路的第一个有效packet包,创建链路 */
    if (p_st_session->p_session_private == NULL)
    {
        /* 初始化MSMQ的私有数据 */
        i_ret = __msmq_init_private(p_st_session);
        if (i_ret != FR_SUCC)
            return APM_L7_ANALYZE_FAIL;

        /* 设置session ID */
        fruuid(p_st_session->arr_session_id);
    }

    p_st_private = (L7session_msmq_private *)p_st_session->p_session_private;

    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __msmq_getdata_req_analysis(p_st_private
                                          , p_st_conn
                                          , p_st_hash_report
                                          , p_st_packet
                                          , p_st_packet->p_payload
                                          , p_st_packet->ui_payload_len);
    }
    else
    {
        i_ret = __msmq_getdata_resp_analysis(p_st_private
                                           , p_st_conn
                                           , p_st_hash_report
                                           , p_st_packet
                                           , p_st_packet->p_payload
                                           , p_st_packet->ui_payload_len);
    }
    return i_ret;
}

